MongoDB Unified Topology
mongodb native driver 3.3以降で使われる接続仕様 根本的に接続周りの仕様が変わる
接続/切断モデルはcluster環境下では適さないから廃止する
これまでのmongodb clientは、DBと接続されている / 接続されていないで動作を変えていた
「接続されている」の定義が曖昧だった
primaryに接続した時点でtrue?
その後secondaryにも接続した?
全nodeのステータスを取得完了した?
primaryとsecondaryの切り替え中は?
など
まとめて「サーバー選択中」というstateで扱う
サーバー選択中は全てのDBのread/writeをブロッキングし、接続復旧を待って実行する
model.find()もmodel.save()もAPIは変更なし。これまで通りawaitするだけでいい
サーバー選択が長すぎる場合はタイムアウトする
serverSelectionTimeoutMSで指定する
mongoose 5.7.0あたりからdeprecation warningが出る DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to MongoClient.connect.
nodeのwarningってどこから出てるかわかりにくいけど、これはmongo native driver npmが出していますshokai.icon
解消方法
MongoDB接続よりも前にフラグを立てる
mongoose.set('useUnifiedTopology', true)
もちろんwarningを消すだけでなく、接続オプションや、切断時の例外処理は見直さなければならない
接続・切断周りの仕様の違い
DBが接続されるまでの間、readもwriteもブロックされる
こういうコードが正しく動く事を目指しているらしい
code:js
const client = new MongoClient('mongodb://llama:drama@localhost:27017/?replicaSet=rs');
const coll = client.db('test').collection('foo');
await coll.insert({ test: 'document' });
const docs = coll.find({ test: 1 }, { readPreference: 'secondary' }).toArray();
console.dir({ docs });
await client.close();
ポイント
client作っていきなりinsertする
接続完了をawaitで待ったりしていない
insert自体はawaitする
接続完了するまでinsertがブロックする
find.toArrayにawait付けてない
これは意図がよくわからないshokai.icon
await忘れてるだけ?
promiseのtoArrayに何か特別な機能がある?
awaitもcallbackもpromiseも使わずに、なぜか同期的にデータが読める?
MongoClient.isConnectedの廃止
廃止されるまで、しばらくは常にtrueが返るらしい
豪快だshokai.icon
unified topologyを選択した場合、connectTimeoutMSオプションは何もしなくなった
しかしこの2つは代替ではなさそうshokai.icon
切断
primaryへのinsert/update中にprimaryが切断
その後いろいろなパターンがある
primaryがすぐ復帰する
secondaryに切り替わる(failover)
primaryがsecondaryに格下げ
primaryがshutdownする
その全ての状態でのタイムアウトとリトライをserverSelectionTimeoutMSで表現する
なるほど、だからisConnectedもconnectTimeoutMSもダメなのかshokai.icon